/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package ar.activity;

import java.util.ArrayList;

import android.app.ProgressDialog;
import android.app.SearchManager;
import android.content.Intent;
import android.content.res.Resources;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Display;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.Toast;
import ar.Location.Constant.Define;
import ar.Location.Map.CameraView;
import ar.Location.Map.CompassView;
import ar.Location.Map.EnhancedMapView;
import ar.Location.Map.InterestingLocations;
import ar.Location.Map.MapOverlay;
import ar.Location.Map.MyOverlayItem;
import ar.Location.Map.OnLongPressListener;
import ar.Location.Map.RotateView;
import ar.Location.Map.SharingLocations;
import ar.Location.PlaceApi.AbsAPI;
import ar.Location.PlaceApi.ApiManager;
import ar.Location.PlaceObject.Place;
import ar.Location.Route.Road;
import ar.activity.R.drawable;
import ar.activity.R.string;
import ar.camera.pojo.GeoLocation;
import ar.globals.Globals;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapView;

public class ARMapActivity extends MapActivity {

	private static final String TAG = "arMapActivity";
	public static boolean isEnableARMap = false;
	
	Resources res = null;

	RelativeLayout layoutParent = null;
	CompassView compassView = null;

	CameraView cameraView = null;
	RotateView rotateView = null;
	EnhancedMapView mapView = null;

	ImageButton imgViewZoomIn = null;
	ImageButton imgViewZoomOut = null;
	LinearLayout zoomView = null;
	Handler handlerZooming = new Handler() {
		public void handleMessage(Message msg) {
			int currentZoomLevel = mapView.getZoomLevel();
			int minZoomLevel = 1;
			int maxZoomLevel = mapView.getMaxZoomLevel();
			if (currentZoomLevel == minZoomLevel) {
				imgViewZoomOut.setEnabled(false);
				imgViewZoomOut.setAlpha(128);
			} else {
				if (currentZoomLevel == maxZoomLevel) {
					imgViewZoomIn.setEnabled(false);
					imgViewZoomIn.setAlpha(128);
				} else {
					imgViewZoomIn.setEnabled(true);
					imgViewZoomOut.setEnabled(true);
					imgViewZoomIn.setAlpha(255);
					imgViewZoomOut.setAlpha(255);
				}
			}
		};
	};

	Display display = null;
	SensorManager sensorManager = null;
	OnLongPressListener longPressListener = null;

	private static ProgressDialog progressDialog = null;

	public static Handler handleSearchLocation = null;
	public static Handler handleDirections = null;
	public static Handler handleShareLocation = null;

	@Override
	public void onCreate(Bundle savedInstanceState) {

		super.onCreate(savedInstanceState);
		
		res = getResources();

		requestWindowFeature(Window.FEATURE_NO_TITLE);
		getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
				WindowManager.LayoutParams.FLAG_FULLSCREEN);

		setContentView(R.layout.map_layout);

		display = getWindowManager().getDefaultDisplay();
		layoutParent = (RelativeLayout) findViewById(R.id.layoutParent);
		compassView = (CompassView) findViewById(R.id.linearCompass);
		cameraView = (CameraView) findViewById(R.id.cameraView);
		rotateView = (RotateView) findViewById(R.id.newRotateView);
		mapView = (EnhancedMapView) findViewById(R.id.enhancedMapView);

		initZoomControl();
		initSensorManager();
		initLongTouchListener();
		initHandlerDirections();
		initHandlerShareLocation();
		initHandlerSearchLocation();

		updateMapState();
	}

	public void updateMapState() {
		if (isEnableARMap) {
			enableARMap();
		} else {
			disableARMap();
		}
	}

	public void initZoomControl() {
		zoomView = (LinearLayout) findViewById(R.id.controlZoom);
		imgViewZoomIn = (ImageButton) findViewById(R.id.imgViewZoomIn);
		imgViewZoomOut = (ImageButton) findViewById(R.id.imgViewZoomOut);

		imgViewZoomIn.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub

				int currentZoomLevel = mapView.getZoomLevel();
				int maxZoomLevel = mapView.getMaxZoomLevel();
				if (currentZoomLevel != maxZoomLevel) {
					mapView.zoomIn();
					handlerZooming.sendEmptyMessage(0);
				}
			}
		});

		imgViewZoomOut.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				int currentZoomLevel = mapView.getZoomLevel();
				int minZoomLevel = 1;
				if (currentZoomLevel != minZoomLevel) {
					mapView.zoomOut();
					handlerZooming.sendEmptyMessage(0);
				}
			}
		});
	}

	public void initSensorManager() {
		sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
	}

	private void initHandlerShareLocation() {
		// TODO Auto-generated method stub
		if (handleShareLocation == null) {
			handleShareLocation = new Handler() {
				@Override
				public void handleMessage(Message msg) {
					// TODO Auto-generated method stub
					if (mapView != null) {
						ArrayList<MyOverlayItem> temps = SharingLocations.listSharingsOnCam;
						int n = temps.size();
						if (n > 0) {
							mapView.clearSharingLocations();
							for (int i = 0; i < n; i++) {
								mapView.addSharingLocation(temps.get(i));
							}
							mapView.invalidate();
						}
					}
				}
			};
		}
	}

	private void handleIntent() {
		// TODO Auto-generated method stub
		Intent intent = getIntent();
		if (intent != null) {
			String str = intent.getStringExtra(Define.ACTION_OUTSIDE_MAP);
			if (str != null) {
				if (str.equals(Define.ACTION_SHOW_DIRECTION)) {
					mapView.updateRoad();
					mapView.invalidate();
					DirectionsActivity.resetParams();
				} else {
					if(Globals.markers != null && Globals.markers.size() > 0) {
						if (str.equals(Define.ACTION_SHOW_LIST_RESULTS)) {
							GeoPoint point0 = Globals.markers.get(0).getPoint();
							if (point0 != null) {
								mapView.setCenter(point0);
							}
						} else {
							if (str.equals(Define.ACTION_SHOW_ITEM)) {
								GeoPoint point0 = Globals.markers.get(0).getPoint();
								if (point0 != null) {
									mapView.setCenter(point0);
								}
							} else {
								if (str.equals(Define.ACTION_TRACKING_ON_MAP)) {
									// ...
								}
							}
						}
					}
				}
			}
		}
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// TODO Auto-generated method stub
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.layout.map_menu, menu);
		return true;
	}

	@Override
	public boolean onPrepareOptionsMenu(Menu menu) {
		// TODO Auto-generated method stub
		MenuItem menuItem = menu.findItem(R.id.menuARMap);
		if (isEnableARMap) {
			menuItem.setTitle(R.string.titleMenuDisableARMap);
			menuItem.setIcon(drawable.disable_ar_map);
		} else {
			menuItem.setTitle(R.string.titleMenuEnableARMap);
			menuItem.setIcon(drawable.map_compass);
		}

		menuItem = menu.findItem(R.id.menuStopTracking);
		if (EnhancedMapView.MODE_TRACKING_ON_MAP) {
			menuItem.setEnabled(true);
		} else {
			menuItem.setEnabled(false);
		}

		return super.onPrepareOptionsMenu(menu);
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		// TODO Auto-generated method stub

		String latitude = Globals.LAT;
		String longitude = Globals.LNG;
		boolean currentGPSIsAvailable = false;
		if (latitude != null && longitude != null) {
			if (latitude.length() > 0 && longitude.length() > 0) {
				currentGPSIsAvailable = true;
			}
		}

		int menuId = item.getItemId();
		switch (menuId) {
		case R.id.menuMapViewOnCam:
			if (isEnableARMap) {
				Toast.makeText(this, res.getString(string.pleaseDisableARMap),
						Toast.LENGTH_SHORT).show();
				return true;
			}
			bindOnCamera(mapView.getListMarkers());
			return true;
		case R.id.menuMyLocation:
			mapView.goToMyLocation();
			return true;
		case R.id.subMenuNormal:
			mapView.setSatellite(false);
			//mapView.setStreetView(false);
			mapView.setTraffic(false);
			return true;
		case R.id.subMenuSatellite:
			mapView.setSatellite(true);
			return true;
		case R.id.subMenuCafe: {
			if (currentGPSIsAvailable) {
				searchByType(ApiManager.googlePlaceApiInstance(), latitude,
						longitude, "cafe", Globals.RADIUS);
			} else {
				Toast.makeText(ARMapActivity.this, res.getString(string.gpsNoSignal),
						Toast.LENGTH_SHORT).show();
			}
		}
			return true;
		case R.id.subMenuFood: {
			if (currentGPSIsAvailable) {
				searchByType(ApiManager.googlePlaceApiInstance(), latitude,
						longitude, "food", Globals.RADIUS);
			} else {
				Toast.makeText(ARMapActivity.this, res.getString(string.gpsNoSignal),
						Toast.LENGTH_SHORT).show();
			}
		}
			return true;
		case R.id.subMenuPark: {
			if (currentGPSIsAvailable) {
				searchByType(ApiManager.googlePlaceApiInstance(), latitude,
						longitude, "park", Globals.RADIUS);
			} else {
				Toast.makeText(ARMapActivity.this, res.getString(string.gpsNoSignal),
						Toast.LENGTH_SHORT).show();
			}
		}
			return true;
		case R.id.subMenuBank: {
			if (currentGPSIsAvailable) {
				searchByType(ApiManager.googlePlaceApiInstance(), latitude,
						longitude, "bank", Globals.RADIUS);
			} else {
				Toast.makeText(ARMapActivity.this, res.getString(string.gpsNoSignal),
						Toast.LENGTH_SHORT).show();
			}
		}
			return true;
		case R.id.subMenuUniversity: {
			if (currentGPSIsAvailable) {
				searchByType(ApiManager.googlePlaceApiInstance(), latitude,
						longitude, "university", Globals.RADIUS);
			} else {
				Toast.makeText(ARMapActivity.this, res.getString(string.gpsNoSignal),
						Toast.LENGTH_SHORT).show();
			}
		}
			return true;
		case R.id.subMenuHospital: {
			if (currentGPSIsAvailable) {
				searchByType(ApiManager.googlePlaceApiInstance(), latitude,
						longitude, "hospital", Globals.RADIUS);
			} else {
				Toast.makeText(ARMapActivity.this, res.getString(string.gpsNoSignal),
						Toast.LENGTH_SHORT).show();
			}
		}
			return true;
		case R.id.subMenuGoogle: {
			if (currentGPSIsAvailable) {
				searchByPoint(ApiManager.googlePlaceApiInstance(), latitude,
						longitude, Globals.RADIUS);
			} else {
				Toast.makeText(ARMapActivity.this, res.getString(string.gpsNoSignal),
						Toast.LENGTH_SHORT).show();
			}
		}
			return true;
		case R.id.subMenuWiki: {
			if (currentGPSIsAvailable) {
				searchByPoint(ApiManager.wikipediaApiInstance(), latitude,
						longitude, Globals.RADIUS);
			} else {
				Toast.makeText(ARMapActivity.this, res.getString(string.gpsNoSignal),
						Toast.LENGTH_SHORT).show();
			}
		}
			return true;
		case R.id.subMenuEvent: {
			if (currentGPSIsAvailable) {
				searchByPoint(ApiManager.eventfulApiInstance(), latitude,
						longitude, Globals.RADIUS);
			} else {
				Toast.makeText(ARMapActivity.this, res.getString(string.gpsNoSignal),
						Toast.LENGTH_SHORT).show();
			}
		}
			return true;
		case R.id.subMenuFlickr: {
			if (currentGPSIsAvailable) {
				searchByPoint(ApiManager.flickrApiInstance(), latitude,
						longitude, Globals.RADIUS);
			} else {
				Toast.makeText(ARMapActivity.this, res.getString(string.gpsNoSignal),
						Toast.LENGTH_SHORT).show();
			}
		}
			return true;
		case R.id.subMenuFoursquare: {
			if (currentGPSIsAvailable) {
				searchByPoint(ApiManager.foursquareApiInstance(), latitude,
						longitude, Globals.RADIUS);
			} else {
				Toast.makeText(ARMapActivity.this, res.getString(string.gpsNoSignal),
						Toast.LENGTH_SHORT).show();
			}
		}
			return true;
		case R.id.menuARMap:
			if (isEnableARMap) {
				disableARMap();
				isEnableARMap = false;
			} else {
				enableARMap();
				isEnableARMap = true;
			}
			return true;
		case R.id.menuSearch:
			onSearchRequested();
			return true;
		case R.id.menuClearMap:
			mapView.clear();
			mapView.invalidate();
			return true;
		case R.id.menuDirections: {
			mapView.clear();
			Intent intent = new Intent(this, DirectionsActivity.class);
			startActivity(intent);
		}
			return true;
		case R.id.menuStopTracking:
			// Stop tracking
			EnhancedMapView.MODE_TRACKING_ON_MAP = false;
			return true;
		default:
			return super.onOptionsItemSelected(item);
		}
	}

	public void bindOnCamera(ArrayList<MyOverlayItem> makers) {
		if (makers == null)
			return;
		Globals.listOfGeoLocations = new ArrayList<GeoLocation>();
		for (int i = 0; i < makers.size(); i++) {
			MyOverlayItem ol = makers.get(i);
			float lat = Float
					.valueOf((float) (ol.getPoint().getLatitudeE6() / 1E6));
			float lng = Float
					.valueOf((float) (ol.getPoint().getLongitudeE6() / 1E6));
			GeoLocation tmp = null;
			if (ol.place != null) {
				tmp = new GeoLocation(lat, lng, ol.place.name);
			} else {
				tmp = new GeoLocation(lat, lng, ol.getTitle());
			}
			Globals.listOfGeoLocations.add(tmp);
		}
		if (Globals.locationIconView != null)
			Globals.locationIconView.getmRenderer().setmListOfGeoLocations(
					Globals.listOfGeoLocations);
		if (Globals.compassView != null)
			Globals.compassView.getmRenderer().setmListOfGeoLocations(
					Globals.listOfGeoLocations);
		Intent i = new Intent(getApplicationContext(), ARCameraActivity.class);
		startActivity(i);
	}

	@Override
	protected void onResume() {
		Log.d(TAG, "On resume");
		super.onResume();

		sensorManager
				.registerListener(rotateView, SensorManager.SENSOR_ORIENTATION,
						SensorManager.SENSOR_DELAY_UI);
		sensorManager
				.registerListener(compassView,
						SensorManager.SENSOR_ORIENTATION,
						SensorManager.SENSOR_DELAY_UI);
		mapView.enableMyLocation();
		mapView.refreshListMarkers();
		mapView.updatePosition();

		handleIntent();
	}

	@Override
	protected void onPause() {
		// TODO Auto-generated method stub
		super.onPause();
		sensorManager.unregisterListener(rotateView);
		sensorManager.unregisterListener(compassView);
		mapView.disableMyLocation();
		mapView.updateLastMapCenter();
	}

	@Override
	protected void onStop() {
		super.onStop();
		sensorManager.unregisterListener(rotateView);
		sensorManager.unregisterListener(compassView);
		mapView.disableMyLocation();
		mapView.updateLastMapCenter();
	}

	@Override
	protected boolean isRouteDisplayed() {
		return false;
	}

	@Override
	public void onNewIntent(Intent intent) {
		setIntent(intent);
		handleSearchIntent(intent);
	}

	private void initHandlerSearchLocation() {
		if (handleSearchLocation == null) {
			handleSearchLocation = new Handler() {
				@Override
				public void handleMessage(Message msg) {
					// TODO Auto-generated method stub

					progressDialog.dismiss();

					MyOverlayItem overlayResult = (MyOverlayItem) msg.obj;

					if (overlayResult != null) {
						mapView.addMarker(overlayResult);
						mapView.showLatestPopUpMarker();
						// mapView.setZoom(15);
						mapView.setCenter(overlayResult.getPoint());
					} else {
						/*
						 * Dialog foundNothingDlg = new AlertDialog.Builder(
						 * arMapActivity.this).setIcon(0)
						 * .setTitle("Failed to find Location")
						 * .setPositiveButton("Ok", null)
						 * .setMessage("Location not found...").create();
						 * foundNothingDlg.show();
						 */
						Toast.makeText(ARMapActivity.this,
								res.getString(string.locationNotFound), 100).show();
					}
				}
			};
		}
	}

	private void initHandlerDirections() {
		// TODO Auto-generated method stub
		Log.d(TAG, "init handler direction");
		if (handleDirections == null) {
			handleDirections = new Handler() {
				@Override
				public void handleMessage(Message msg) {
					// TODO Auto-generated method stub
					if (msg != null) {
						Log.d(TAG, "direct");
						Road mRoad = (Road) msg.obj;
						if (mRoad != null) {
							MapOverlay.setRoad(mRoad);
							mapView.updateRoad();
							mapView.invalidate();
							DirectionsActivity.resetParams();
						}
					}
				}
			};
		}
	}

	private void initLongTouchListener() {
		// TODO Auto-generated method stub
		longPressListener = new OnLongPressListener() {
			@Override
			public void onLongPress(final MapView view,
					final GeoPoint longpressLocation) {
				// TODO Auto-generated method stub
				runOnUiThread(new Runnable() {
					public void run() {
						// Insert your longpress action here
						findLocation(longpressLocation);
					}
				});
			}
		};
		mapView.setOnLongpressListener(longPressListener);
	}

	private void enableARMap() {
		// TODO Auto-generated method stub
		layoutParent.removeAllViews();

		cameraView.getLayoutParams().width = display.getWidth();
		cameraView.getLayoutParams().height = display.getHeight() / 2;

		rotateView.removeAllViews();
		rotateView.addView(mapView);
		rotateView.getLayoutParams().width = display.getWidth();
		rotateView.getLayoutParams().height = display.getHeight() / 2;

		layoutParent.addView(cameraView);
		layoutParent.addView(rotateView);
		layoutParent.addView(compassView);
		layoutParent.addView(zoomView);

		/*
		 * mapView.getController().setZoom(18); mapView.setMyCenter();
		 */
	}

	private void disableARMap() {

		rotateView.removeAllViews();

		layoutParent.removeAllViews();
		layoutParent.addView(mapView);
		layoutParent.addView(zoomView);
		layoutParent.addView(compassView);

		/*
		 * mapView.getController().setZoom(15); mapView.setMyCenter();
		 */
	}

	private void handleSearchIntent(Intent intent) {
		if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
			String strSearch = intent.getStringExtra(SearchManager.QUERY);
			if (strSearch != null && strSearch.length() > 0) {
				findLocation(strSearch);
			} else {
				Toast.makeText(this, "Input is not valid!", Toast.LENGTH_SHORT)
						.show();
			}
		}
	}

	private void findLocation(final String strSearch) {
		// TODO Auto-generated method stub
		progressDialog = ProgressDialog.show(ARMapActivity.this,
				res.getString(string.processing), res.getString(string.findingLocation), true, false);

		Thread threadFindLocation = new Thread(new Runnable() {
			@Override
			public void run() {
				// TODO Auto-generated method stub

				if (strSearch.length() > 0) {
					MyOverlayItem overlayResult = mapView.search(strSearch);
					Message msg = new Message();
					msg.obj = overlayResult;
					handleSearchLocation.sendMessage(msg);
				}
			}
		});
		threadFindLocation.start();
	}

	private void findLocation(final GeoPoint location) {
		// TODO Auto-generated method stub
		progressDialog = ProgressDialog.show(ARMapActivity.this,
				res.getString(string.processing), res.getString(string.findingLocation), true, false);

		Thread threadFindLocation = new Thread(new Runnable() {
			@Override
			public void run() {
				// TODO Auto-generated method stub

				if (location != null) {
					MyOverlayItem overlayResult = mapView.search(location);
					Message msg = new Message();
					msg.obj = overlayResult;
					handleSearchLocation.sendMessage(msg);
				}
			}
		});
		threadFindLocation.start();
	}

	public void searchByPoint(final AbsAPI apiSearch, final String latitude,
			final String longitude, final int radiusMetters) {
		progressDialog = ProgressDialog.show(ARMapActivity.this,
				res.getString(string.processing), res.getString(string.findingLocation), true, false);
		Thread thread = new Thread(new Runnable() {

			@Override
			public void run() {
				// TODO Auto-generated method stub
				ArrayList<Place> listResults = apiSearch
						.getListPlacesByGeoPoint(latitude, longitude,
								radiusMetters);
				Message msg = new Message();
				msg.obj = listResults;
				if (InterestingLocations.handlerSearchNearBy != null) {
					InterestingLocations.handlerSearchNearBy.sendMessage(msg);
				}
				progressDialog.dismiss();
			}
		});
		thread.start();
	}

	public void searchByType(final AbsAPI apiSearch, final String latitude,
			final String longitude, final String type, final int radiusMetters) {
		progressDialog = ProgressDialog.show(ARMapActivity.this,
				res.getString(string.processing), res.getString(string.findingLocation), true, false);
		Thread thread = new Thread(new Runnable() {

			@Override
			public void run() {
				// TODO Auto-generated method stub
				ArrayList<Place> listResults = apiSearch.getListPlacesByType(
						latitude, longitude, type, radiusMetters);
				Message msg = new Message();
				msg.obj = listResults;
				if (InterestingLocations.handlerSearchNearBy != null) {
					InterestingLocations.handlerSearchNearBy.sendMessage(msg);
				}
				progressDialog.dismiss();
			}
		});
		thread.start();
	}

	@Override
	public void onBackPressed() {
		// TODO Auto-generated method stub
		super.onBackPressed();
		DirectionsActivity.resetParams();
		mapView.updateLastMapCenter();
		mapView.clearListOverlays();
		finish();
	}
}
